package com.waves.camear;

import org.bytedeco.javacv.*;
import org.bytedeco.javacv.Frame;

import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

public class JavaCVWebcamMonitor extends JFrame {

    private CanvasFrame canvasFrame; // 用于显示摄像头图像的 CanvasFrame
    private JButton captureButton; // 抓取图像的按钮
    private JLabel statusLabel; // 显示状态信息的标签
    private OpenCVFrameGrabber grabber; // OpenCVFrameGrabber 用于从摄像头捕获帧
    private volatile boolean running = true; // 控制抓取线程的标志

    public JavaCVWebcamMonitor() {
        super("JavaCV 摄像头监控"); // 设置窗口标题

        // 1. 初始化 OpenCVFrameGrabber
        grabber = new OpenCVFrameGrabber(0); // 0 表示默认摄像头
        try {
            grabber.start(); // 启动抓取器
        } catch (FrameGrabber.Exception e) {
            JOptionPane.showMessageDialog(this, "无法启动摄像头: " + e.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
            System.exit(1); // 退出程序
        }

        // 2. 创建 CanvasFrame
        canvasFrame = new CanvasFrame("摄像头"); // 设置 CanvasFrame 标题
        canvasFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 关闭窗口时退出程序
        canvasFrame.setCanvasSize(grabber.getImageWidth(), grabber.getImageHeight()); // 设置 Canvas 大小

        // 3. 创建抓取按钮
        captureButton = new JButton("抓取图像");
        captureButton.addActionListener(e -> {
            captureImage(); // 调用抓取图像的方法
        });

        // 4. 状态标签
        statusLabel = new JLabel("摄像头准备就绪");
        statusLabel.setHorizontalAlignment(SwingConstants.CENTER); // 居中显示

        // 5. 布局 UI
        JPanel controlPanel = new JPanel(new FlowLayout());
        controlPanel.add(captureButton); // 添加抓取按钮

        JPanel mainPanel = new JPanel(new BorderLayout());
        mainPanel.add(controlPanel, BorderLayout.SOUTH); // 添加控制面板到南部
        mainPanel.add(statusLabel, BorderLayout.NORTH); // 添加状态标签到北部

        getContentPane().add(mainPanel);

        // 6. 窗口设置
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 关闭窗口时退出程序
        pack(); // 自动调整大小
        setLocationRelativeTo(null); // 居中显示窗口
        setVisible(true); // 显示窗口

        // 7. 启动抓取线程
        new Thread(() -> {
            try {
                while (running) {
                    Frame frame = grabber.grab(); // 抓取一帧
                    if (frame != null) {
                        canvasFrame.showImage(frame); // 在 CanvasFrame 中显示图像
                    } else {
                        // 如果抓取失败，尝试重新启动抓取器
                        try {
                            grabber.restart();
                        } catch (FrameGrabber.Exception e) {
                            statusLabel.setText("摄像头故障: " + e.getMessage());
                            running = false; // 停止线程
                            break;
                        }
                    }
                    Thread.sleep(30); // 控制帧率 (大约 30 帧/秒)
                }
            } catch (FrameGrabber.Exception | InterruptedException e) {
                statusLabel.setText("抓取线程错误: " + e.getMessage());
            } finally {
                try {
                    grabber.stop(); // 停止抓取器
                    grabber.close(); // 关闭抓取器
                    canvasFrame.dispose(); // 关闭 CanvasFrame
                } catch (FrameGrabber.Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    private void captureImage() {
        try {
            Frame frame = grabber.grab();
            if (frame != null) {
                BufferedImage image = converterToImage(frame);
                if (image != null) {
                    // 将图像保存到文件 (例如, 在项目目录中)
                    File outfile = new File("captured_image_" + System.currentTimeMillis() + ".png");
                    ImageIO.write(image, "png", outfile);
                    statusLabel.setText("图像已抓取并保存到: " + outfile.getAbsolutePath()); // 更新状态标签
                } else {
                    statusLabel.setText("无法将帧转换为 BufferedImage.");
                }
            } else {
                statusLabel.setText("无法抓取图像.");
            }
        } catch (IOException e) {
            statusLabel.setText("抓取或保存图像时发生错误: " + e.getMessage());
            e.printStackTrace(); // 打印堆栈跟踪
        }
    }

    private BufferedImage converterToImage(Frame frame) {
        Java2DFrameConverter converter = new Java2DFrameConverter();
        BufferedImage bufferedImage = converter.getBufferedImage(frame);
        return bufferedImage;
    }

    public static void main(String[] args) {
        // 确保 Swing 组件在事件分发线程上创建和更新.
        // 创建并启动 JavaCVWebcamMonitor
        SwingUtilities.invokeLater(JavaCVWebcamMonitor::new);
    }

    @Override
    public void dispose() {
        running = false; // 停止抓取线程
        super.dispose();
    }
}
